const loadBlock = function(map, blockObject) {
    let state = blockObject.state
    let blockArray = blockObject.block[state]
    let len = blockArray.length
    let coordinates = []
    let topY = map[0].length / 2 - len / 2
    for (let i = 0; i < len; i++) {
        for (let j = 0; j < len; j++) {
            let n = blockArray[i][j]
            if (n !== 0) {
                map[i][topY + j] = n * blockObject.color
                coordinates.push([i, topY + j])
            }
        }
    }
    return coordinates
}

const nextMoveCoordinates = function(currentCoors, offsetX, offsetY = 0) {
    let copy = JSON.parse(JSON.stringify(currentCoors))
    for (let i = 0; i < copy.length; i++) {
        copy[i][0] += offsetX
        copy[i][1] += offsetY
    }
    return copy
}


const currentBottomLeft = function(currentCoors) {
    let bottom = currentCoors[0][0]
    let left = currentCoors[0][1]
    for (let i = 1; i < currentCoors.length; i++) {
        let x = currentCoors[i][0]
        let y = currentCoors[i][1]
        if (bottom < x) {
            bottom = x
        }
        if (left > y) {
            left = y
        }
    }
    return { bottom, left }
}
const nextRotateCoordinates = function(currentCoors, blockObject) {
    let coors = blockObject.nextStateCoordinates()
    let bottomLeft = currentBottomLeft(currentCoors)
    let nextCoors = []
    coors.forEach(items => {
        let x = bottomLeft.bottom - 3 + items[0]
        let y = bottomLeft.left + items[1]
        nextCoors.push([x, y])
    })
    return nextCoors
}
const nextCoordinates = function(currentCoors, direction, blockObject) {
    if (blockObject !== undefined && direction === 'rotate') {
        return nextRotateCoordinates(currentCoors, blockObject)
    }
    let directions = {
        left: nextMoveCoordinates(currentCoors, 0, -1),
        right: nextMoveCoordinates(currentCoors, 0, 1),
        down: nextMoveCoordinates(currentCoors, 1),
    }
    return directions[direction]
}


const coordinateValid = function(map, x, y) {
    let len1 = map.length
    let len2 = map[0].length
    return x >=0 && x < len1 && y >=0 && y < len2
}
const collide = function(map, currentCoors, nextCoordinates) {
    for (let i = 0; i < nextCoordinates.length; i++) {
        let coors = nextCoordinates[i]
        let x = coors[0]
        let y = coors[1]
        let cantMove = !coordinateValid(map, x, y) || map[x][y] !== 0 && !subArray(currentCoors, [x, y])
        if (cantMove) {
            return true
        }
    }
    return false
}
const assignNextAndClearCurrent = function(map, currentCoors, nextCoors) {
    let color = 0
    currentCoors.forEach((coor, i) => {
        let x = coor[0]
        let y = coor[1]
        if (coordinateValid(map, x, y)) {
            color = map[x][y]
            map[x][y] = 0
        }
    })
    nextCoors.forEach((coor) => {
        let x = coor[0]
        let y = coor[1]
        if (coordinateValid(map, x, y)) {
            map[x][y] = color
        }
    })
}

const clearLines = function(game, width = 10) {
    let scores = {
        1: 1,
        2: 3,
        3: 6,
        4: 10,
    }
    let count = 0
    let bottom = currentBottomLeft(game.currentCoors).bottom
    for (let i = bottom - 3; i < bottom + 1; i++) {
        if (!game.map[i].includes(0)) {
            game.map.splice(i, 1)
            game.lineNumber += 1
            game.map.splice(0, 0, zeroLine(width))
            count += 1
        }
    }
    if (count !== 0) {
        game.score += scores[count]
    }
    game.updateLevel()
}

const loadNewBlock = function(game) {
    let newBlock = Block()
    game.currentBlock = game.nextBlock
    game.nextBlock = newBlock
    game.currentCoors = loadBlock(game.map, game.currentBlock)
}
const lock = function(game) {
    let nextCoors = nextCoordinates(game.currentCoors, 'down', game.currentBlock)
    while (!collide(game.map, game.currentCoors, nextCoors)) {
        move(game, 'down')
        nextCoors = nextCoordinates(game.currentCoors, 'down', game.currentBlock)
    }
    if (arraySum(game.map[4]) !== 0) {
        gameOver(game)
    } else {
        freeze(game)
    }
}
const freeze = function(game) {
    clearLines(game)
    loadNewBlock(game)
    reload(game)
}
const move = function(game, direction) {
    let nextCoors = nextCoordinates(game.currentCoors, direction, game.currentBlock)
    if(!collide(game.map, game.currentCoors, nextCoors)) {
        if (game.currentBlock !== undefined && direction === 'rotate') {
            game.currentBlock.state = (game.currentBlock.state + 1) % 4
        }
        assignNextAndClearCurrent(game.map, game.currentCoors, nextCoors)
        game.currentCoors = nextCoors
        reload(game)
    } else if (direction === 'down') {
        if (arraySum(game.map[4]) !== 0) {
            gameOver(game)
        } else {
            freeze(game)
        }
    }
}

const gameOver = function(game) {
    let gameOverDiv = e('#id-div-gameover')
    gameOverDiv.classList.add('show')
    clearTimeout(game.timer)
    clearTimeout(game.timer1)
    removeEvents(game)
}

const loop = function(game, direction) {
    move(game, direction)
    game.timer = setTimeout(() => {
        loop(game, direction)
    }, 1000 / game.fps)
}


